<?php
//设置异常处理的函数
set_exception_handler(array('Sing_Core', 'handleException'));

//欲注册的自动装载函数。
if(function_exists('spl_autoload_register')) {
    spl_autoload_register(array('Sing_Core', 'autoload'));
} else {
    function __autoload($class) {
            return core::autoload($class);
    }
}

C::init();

class Sing_Core{
	
	private static $_imports;
	private static $config = array();
	
	private static  $_var = array();
	private static $_app;
	
	private static $init_db = true;
	private static $_tables;
	private static $_memory;
	private static $_redis;
	
	private static $superglobal = array(
		'GLOBALS' => 1,
		'_GET' => 1,
		'_POST' => 1,
		'_REQUEST' => 1,
		'_COOKIE' => 1,
		'_SERVER' => 1,
		'_ENV' => 1,
		'_FILES' => 1,
		'HTTP_RAW_POST_DATA'=>1
	);
	
	
	public function __construct() {
		$this->init();
	}
	
	public static function init(){
		self::_init_env();
		self::_init_config();
		self::_init_input();
		self::_init_output();
	}
	
	private static function _init_config() {		
		
		$_config = array();
		@include SING_CONFIG.'/config_global.php';		
		
		
		if(empty($_config['security']['authkey'])) {
			$_config['security']['authkey'] = md5($_config['cookie']['cookiepre'].$_SERVER['HTTP_USER_AGENT']);
		}
		
		define('STATICURL', !empty($_config['output']['staticurl']) ? $_config['output']['staticurl'] : 'static/');		
		global $_G;
			
		$_G = array(
				'uid' => 0,
				'username' => '',
				'_uid' => 0,
				'_username' => '',
				'adminid' => 0,
				'groupid' => 0,
				'deid' => 0,
				'logintime' => '',
				'lasttime' => '',
				'relname' => '',
				'status' => 0,
				'inajax' => false,
				'inApi'=>false,
				'formhash' => '',
				'connectguest' => 0,
				'timestamp' => TIME,
				'starttime' => microtime(true),
				'clientip' => self::_get_client_ip(),
				'remoteport' => $_SERVER['REMOTE_PORT'],
				'HTTP_REFERER'=> $_SERVER["HTTP_REFERER"],
				'referer' => '',
				'charset' => '',
				'gzipcompress' => '',
				'authkey' => '',
				'timenow' => array(),
				'widthauto' => 0,
				'disabledwidthauto' => 0,
		
				'PHP_SELF' => '',
				'siteurl' => '',
				'HOST_URL' =>'',
				'FULL_URL' =>'',
	
				'siteroot' => '',
				'siteport' => '',		

				'config' => array(),
				'setting' => array(),
				'member' => array(),
				'group' => array(),
				'cookie' => array(),
				'style' => array(),
				'cache' => array(),
				'session' => array(),
				'lang' => array(),

				'act'=>'',
				's'=>'',
				
				'mobile' => '',
				'mobiletpl' => array('1' => 'mobile', '2' => 'touch', '3' => 'wml','yes' => 'mobile'),
		);
		
		
		
		$_G['PHP_SELF'] = dhtmlspecialchars(self::_get_script_url());
		$_G['basescript'] = CURSCRIPT;
		$_G['basefilename'] = basename($_G['PHP_SELF']);
		$sitepath = substr($_G['PHP_SELF'], 0, strrpos($_G['PHP_SELF'], '/'));
		if(defined('IN_API')) {
			$sitepath = preg_replace("/\/api\/?.*?$/i", '', $sitepath);
		} elseif(defined('IN_ARCHIVER')) {
			$sitepath = preg_replace("/\/archiver/i", '', $sitepath);
		}
		$_G['isHTTPS'] = ($_SERVER['HTTPS'] && strtolower($_SERVER['HTTPS']) != 'off') ? true : false;
		$_G['siteurl'] = dhtmlspecialchars('http'.($_G['isHTTPS'] ? 's' : '').'://'.$_SERVER['HTTP_HOST'].$sitepath.'/');
		$_G['HOST_URL'] = dhtmlspecialchars('http'.($_G['isHTTPS'] ? 's' : '').'://'.$_SERVER['HTTP_HOST'].'/');
		$_G['FULL_URL'] = dhtmlspecialchars('http'.($_G['isHTTPS'] ? 's' : '').'://'.$_SERVER['HTTP_HOST'].$sitepath.$_SERVER['REQUEST_URI']);
		$url = parse_url($_G['siteurl']);
		$_G['siteroot'] = isset($url['path']) ? $url['path'] : '';
		$_G['siteport'] = empty($_SERVER['SERVER_PORT']) || $_SERVER['SERVER_PORT'] == '80' || $_SERVER['SERVER_PORT'] == '443' ? '' : ':'.$_SERVER['SERVER_PORT'];
		
		if(defined('SUB_DIR')) {
			$_G['siteurl'] = str_replace(SUB_DIR, '/', $_G['siteurl']);
			$_G['siteroot'] = str_replace(SUB_DIR, '/', $_G['siteroot']);
		}
		//self::$config = $_config;
		$_G['config'] = $_config;
		self::$_var = & $_G;
		
	}
	private static function _init_env() {
		if(PHP_VERSION < '5.3.0') {
			set_magic_quotes_runtime(0);
		}
		
		define('MAGIC_QUOTES_GPC', function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc());
		define('ICONV_ENABLE', function_exists('iconv'));
		define('MB_ENABLE', function_exists('mb_convert_encoding'));
		define('EXT_OBGZIP', function_exists('ob_gzhandler'));
		
		define('TIME', time());		
		
		//echo SING_PATH.'/source/function/function_core.php';
		//加载核心函数库
		if(!defined('SING_CORE_FUNCTION') && !@include(SING_PATH.'/source/function/function_core.php')) {
			exit('function_core.php is missing');
		}
		
		if(function_exists('ini_get')) {
			$memorylimit = @ini_get('memory_limit');
			if($memorylimit && return_bytes($memorylimit) < 33554432 && function_exists('ini_set')) {
				ini_set('memory_limit', '128m');
			}
		}
		
		define('IS_ROBOT', checkrobot());
		
		foreach ($GLOBALS as $key => $value) {
			if (!isset(self::$superglobal[$key])) {
				$GLOBALS[$key] = null; unset($GLOBALS[$key]);
			}
		}
	}
	
	private static function _init_input() {
		if (isset($_GET['GLOBALS']) ||isset($_POST['GLOBALS']) ||  isset($_COOKIE['GLOBALS']) || isset($_FILES['GLOBALS'])) {
			system_error('request_tainting');
		}
		if(MAGIC_QUOTES_GPC) {
			$_GET = dstripslashes($_GET);
			$_POST = dstripslashes($_POST);
			$_COOKIE = dstripslashes($_COOKIE);
		}
		if(defined("InApi")){
                    $_GET = convertJsonStringToJsonArray($_GET);
                    $_POST = convertJsonStringToJsonArray($_POST);
                }
		$prelength = strlen(self::$_var['config']['cookie']['cookiepre']);
		foreach($_COOKIE as $key => $val) {
			if(substr($key, 0, $prelength) == self::$_var['config']['cookie']['cookiepre']) {
				self::$_var['cookie'][substr($key, $prelength)] = $val;
			}
		}
		
		if($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST)) {
			$_GET = array_merge($_GET, $_POST);
		}
		
		if(isset($_GET['page'])) {
			$_GET['page'] = rawurlencode($_GET['page']);
		}		
		
		self::$_var['inajax'] = is_ajax_request();
		self::$_var['inApi'] = defined('inApi');
		if(empty(self::$_var['config']['input']['compatible'])) {
			foreach($_GET as $k => $v) {
				self::$_var['g_'.$k] = daddslashes($v);
			}
		}else{
			foreach($_GET as $k => $v) {
				self::$_var['g_'.$k] = $v;
			}
		}
		//self::$_var['mod'] = $_GET['file'];
		self::$_var['act'] = $_GET['act'];
		self::$_var['s'] = $_GET['s'];
		
		$_REQUEST = daddslashes($_REQUEST);	
	}	
	private static function _init_output() {
		
		
		// 压缩输出
		if(!empty($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === false) {
            //最开始的写法
//			$this->config['output']['gzip'] = false;

            //由于3d签到接口程序报这里有错，修改此处为静态调用，config数组本身就是静态变量；
            Sing_Core::$config['output']['gzip'] = false;
		}
		

		
		$allowgzip = self::$_var['config']['output']['gzip'] && empty(self::$_var['inajax']) && self::$_var['mod'] != 'attachment' && EXT_OBGZIP && !self::$_var['inApi'];
		setglobal('gzipcompress', $allowgzip);
		
		if(!ob_start($allowgzip ? 'ob_gzhandler' : null)) {
			ob_start();
		}

		setglobal('charset', self::$_var['config']['output']['charset']);
		define('CHARSET', self::$_var['config']['output']['charset']);
		if(self::$_var['config']['output']['forceheader']) {
			@header('Content-Type: text/html; charset='.CHARSET);
		}
	}
	
	public static function handleException($exception){
		//var_dump($expression);
		SING_error::exception_error($exception);
	}
	
	//加载文件
	public static function import($name, $folder = '', $force = true) {
		$key = $folder.$name;
		if(!isset(self::$_imports[$key])) {
			if (strpos($name, MODULE) !== false) {
				$path = '';
				if (strpos($name, 'dbt') === false) $filename = $name.'.php';
				else{
					$pre = basename(dirname($name));
					$filename = dirname($name).'/'.$pre.'_'.basename($name).'.php';
				}
			}else{
				$path = SING_PATH.'/source/'.$folder;				
				if(strpos($name, '/') !== false) {
					$pre = basename(dirname($name));
					$filename = $path.dirname($name).'/'.$pre.'_'.basename($name).'.php';
				} else {
					$filename = $path.$name.'.php';
				}
			}
	
			if(is_file($filename)) {
				include $filename;
				self::$_imports[$key] = true;
	
				return true;
			} elseif(!$force) {
				return false;
			} else {
				throw new Exception('需要加载的文件不存在: '.$filename);
			}
		}
		return true;
	}
	
	
	public static function autoload($class) {
		$class = strtolower($class);		
		if(strpos($class, '_') !== false ){
			list($folder) = explode('_', $class);
			$file = MODULE.'/'.$folder.'/class/'.$class.'.class';
		}
		if(!is_file($file.'.php'))	$file = MODULE.'/'.$class.'/class/'.$class.'.class';
		if(!is_file($file.'.php')){
			if(strpos($class, '_') !== false) {
				list($folder) = explode('_', $class);
				$file = 'class/'.$folder.'/'.substr($class, strlen($folder) + 1);
			}else {
				$file = 'class/'.$class;							
			}
		}
		
		try{
	
			self::import($file);
			return true;
	
		}catch (Exception $exc){	
			$trace = $exc->getTrace();
			foreach ($trace as $log) {
				if(empty($log['class']) && $log['function'] == 'class_exists') {
					return false;
				}
			}
			SING_error::exception_error($exc);
		}
	}
	
	private static function _get_client_ip() {
		$ip = $_SERVER['REMOTE_ADDR'];
		if (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
			$ip = $_SERVER['HTTP_CLIENT_IP'];
		} elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
			foreach ($matches[0] AS $xip) {
				if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {
					$ip = $xip;
					break;
				}
			}
		}
		return $ip;
	}
	
	private static function _get_script_url() {
		if(!isset(self::$_var['PHP_SELF'])){
			$scriptName = basename($_SERVER['SCRIPT_FILENAME']);
			if(basename($_SERVER['SCRIPT_NAME']) === $scriptName) {
				self::$_var['PHP_SELF'] = $_SERVER['SCRIPT_NAME'];
			} else if(basename($_SERVER['PHP_SELF']) === $scriptName) {
				self::$_var['PHP_SELF'] = $_SERVER['PHP_SELF'];
			} else if(isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $scriptName) {
				self::$_var['PHP_SELF'] = $_SERVER['ORIG_SCRIPT_NAME'];
			} else if(($pos = strpos($_SERVER['PHP_SELF'],'/'.$scriptName)) !== false) {
				self::$_var['PHP_SELF'] = substr($_SERVER['SCRIPT_NAME'],0,$pos).'/'.$scriptName;
			} else if(isset($_SERVER['DOCUMENT_ROOT']) && strpos($_SERVER['SCRIPT_FILENAME'],$_SERVER['DOCUMENT_ROOT']) === 0) {
				self::$_var['PHP_SELF'] = str_replace('\\','/',str_replace($_SERVER['DOCUMENT_ROOT'],'',$_SERVER['SCRIPT_FILENAME']));
				self::$_var['PHP_SELF'][0] != '/' && self::$_var['PHP_SELF'] = '/'.self::$_var['PHP_SELF'];
			} else {
				system_error('request_tainting');
			}
		}
		return self::$_var['PHP_SELF'];
	}
	public static function t($name) {
		return self::_make_obj($name, 'dbt', SING_TABLE_EXTENDABLE);
	}

	protected static function _make_obj($name, $type, $extendable = false, $p = array()) {
		$m = null;

		if($name[0] === '#') {
			list(, $m, $name) = explode('#', $name);
		}
		$cname = $type.'_'.$name;
		//$cname = $type.'_'.$m.'_'.$name;
		if(!isset(self::$_tables[$cname])) {
			if(!class_exists($cname, false)) {
				self::import(($m ? MODULE.'/'.$m.'/class' : 'class').'/'.$type.'/'.$name);
			}
			if($extendable) {
				self::$_tables[$cname] = new discuz_container();
				switch (count($p)) {
					case 0:	self::$_tables[$cname]->obj = new $cname();break;
					case 1:	self::$_tables[$cname]->obj = new $cname($p[1]);break;
					case 2:	self::$_tables[$cname]->obj = new $cname($p[1], $p[2]);break;
					case 3:	self::$_tables[$cname]->obj = new $cname($p[1], $p[2], $p[3]);break;
					case 4:	self::$_tables[$cname]->obj = new $cname($p[1], $p[2], $p[3], $p[4]);break;
					case 5:	self::$_tables[$cname]->obj = new $cname($p[1], $p[2], $p[3], $p[4], $p[5]);break;
					default: $ref = new ReflectionClass($cname);self::$_tables[$cname]->obj = $ref->newInstanceArgs($p);unset($ref);break;
				}
			} else {
				self::$_tables[$cname] = new $cname();
			}
		}
		return self::$_tables[$cname];
	}
	public static function Auth2($token, $user , $nonce){
	
		$timestamp = TIME;
		$tmpArr = array($token, $timestamp, $nonce , $user);
		sort($tmpArr,SORT_STRING);
		$tmpStr = implode( $tmpArr );
		$tmpStr = sha1( $tmpStr );
		
		return $tmpStr;
	}
	
	public static function memory() {
		if(!self::$_memory) {
			self::$_memory = new sing_memory();
			self::$_memory->init(self::$_var['config']['memory']);
		}
		return self::$_memory;
	}
	public static function redis(){
		if(!self::$_redis) {
			self::$_redis = new sing_redis();
			self::$_redis->init(self::$_var['config']['memory']);
		}
		return self::$_redis;
	}
}

class C extends Sing_Core{}
class DB extends Sing_database {}
$_app = new SING_other();